;load kernel to ram
;switch to protect mode

org 7c00h

jmp start

%include "config.asm"
%include "boot_lib.asm"

[bits 16]
;build gdt
build_gdt:
	;calc GDT address
	mov eax, [pgdt + 2]
	xor edx, edx ;EAX = addr of pgdt
	mov ebx, 16
	div ebx ;eax = addr / 16;  EDX = addr % 16
	mov ds, eax
	mov ebx, edx

	;ignore 0#
	;1#, 4GB data, base = 0, len = 0x10 0000
	mov dword [ebx + SelAllData], DescBaseL(0, 0x100000)
	mov dword [ebx + SelAllData + 4], \
		Descriptor(DA_LIMIT_4K, DA_DRW) | DescBaseH(0, 0x100000)

	;2#, 512B, init code, len = 0x200
	mov dword [ebx + SelCoreCode], DescBaseL(0x7c00, 0x200)
	mov dword [ebx + SelCoreCode + 4], \
		Descriptor(DA_LIMIT_1B, DA_C) |  DescBaseH(0x7c00, 0x200)

	;3#, 4KB, stack, len = 0x1000 = 4KB
	mov dword [ebx + SelStack], DescBaseL(0x7c00, StackLen(0x1000))
	mov dword [ebx + SelStack + 4], \
		Descriptor(DA_LIMIT_4K, DA_DRWE) | DescBaseH(0x7c00, StackLen(0x1000))

	;4#, VGA memory
	mov dword [ebx + SelVgaData], DescBaseL(0xb8000, 0x8000)
	mov dword [ebx + SelVgaData + 4], \
		Descriptor(DA_LIMIT_1B, DA_DRW) | DescBaseH(0xb8000, 0x8000)

	;fill GDT size
	mov word [cs:pgdt], GDT_SIZE
	lgdt [cs:pgdt] ;load GDT
	ret

start:
	;init
	mov ax, cs
	mov ds, ax
	mov es, ax
	mov ss, ax
	mov sp, 0
	
	;show boot message
	call clrScreen

	mov ax, BootMsg
	mov cx, BootMsg_len
	call dispStr

	call build_gdt
	call open_a20 ;open A20
	cli
	;set cr0.pe
	mov eax, cr0
	or eax, 11
	mov cr0,eax

	;enter 32b protect mode
	jmp dword SelCoreCode:(load_kernel - 0x7c00)

[bits 32]
load_kernel:
	;init ds
	mov eax, SelAllData
	mov ds, eax
	;init ss
	mov eax, SelStack
	mov ss, eax
	mov esp, 0

	;read kernal image from disk
	mov edi, kernel_base_addr
	mov eax, kernel_start_sector
	mov ebx, kernel_base_addr
	;from kernel_start_sector sector, read kernel to ss:ebx
	call read_kernel

	mov eax, pgdt
	call setup_kernel_gdt
	;start kernel
	jmp far [edi + KERNEL_HEAD_ENTRY]

	jmp $

;msg
BootMsg: db "booting ...", 0dh, 0ah
BootMsg_len equ ($ - BootMsg)

;GDT
pgdt dw 0
	dd gdt_base_addr

;boot magic number 0xaa55
times 510 - ($ - $$) db 0
dw 0xaa55

